package ee.objectCloner.impl.cloners;

import java.util.ArrayList;
import java.util.List;

import ee.objectCloner.CustomCloner;
import ee.objectCloner.ObjectCloner;

public class ArrayListCloner implements CustomCloner {

	@Override
	public List<?> clone(Object source, ObjectCloner objectCloner) {
		
		List<?> sourceList = (List<?>) source;
		List<Object> destination = new ArrayList<Object>(sourceList.size());
		
		for (Object o : sourceList) {
			destination.add(objectCloner.clone(o));
		}
		
		return destination;
	}

	@Override
	/**
	 * Checks if an index is available in the destination. If it is, it will be used as destination 
	 * for the copy. Otherwise a clone is used.
	 */
	public void copy(Object source, Object destination, ObjectCloner objectCloner) {
		if (source.equals(destination))
		{
			return;
		}
		
		List<?> sourceList = (List<?>) source;
		
		@SuppressWarnings("unchecked")
		List<Object> destinationList = (List<Object>) destination;
		
		int index = -1;
		int sourceSize = sourceList.size();
		int destinationSize = destinationList.size();
		int maxIndex = destinationSize - 1;
		
		boolean exceededMaxIndex = false;
		
		while (++index < sourceSize) {
			
			exceededMaxIndex = index > maxIndex;
			
			Object destinationValue = exceededMaxIndex ? null : destinationList.get(index);
			
			Object value = objectCloner.copyOrClone(sourceList.get(index), destinationValue);
			
			if (exceededMaxIndex) {
				destinationList.add(value);
			} else
			{
				destinationList.set(index, value);
			}
		}
		
		while (index < destinationSize) {
			destinationList.remove(index++);
		}
	}

	@Override
	public boolean canClone(Class<?> type) {
		return type.equals(List.class) || type.equals(ArrayList.class);
	}

	@Override
	public boolean canCopy(Class<?> sourceType, Class<?> destinationType) {
		return List.class.isAssignableFrom(sourceType) && List.class.isAssignableFrom(destinationType);
	}

	
}
